//
// Created by ttao on 2022/8/4.
//

#include <stddef.h>
#include <lock.h>
#include <unix/http_log.h>

/* ================ start of Stack.c ================ */
/*
 * eg:  初始化栈
        stack s;
        char *c[100];
        initStack(&s, c, sizeof(c)/sizeof(char *));
 */
//清空栈
void stack_clear(stack *s)
{
    while(s->point!=0)
    {
        s->head[s->point-1] = NULL;
        s->point--;
    }
}
//堆栈是否为空
int isempty(stack *s)
{
    return(s->point == 0);
}
//入栈函数
int push(stack *s, void *node)
{
    if(s->point < s->maxlen)
    {
        s->head[(s->point)++] = node;
        return(0);
    }
    else
        return(-1);
}
//出栈函数
void *pop(stack *s)
{
    if(s->point >0)
        return(s->head[--(s->point)]);
    else
        return(0);
}
/* ================ end of Stack.c ================ */

/* ================ start of Queue.c ================ */
/*
 *  eg: 队列
    struct Queue queue;
    initQueue(&queue, 100);

    add(queue, dtsnew("hello"));
    dts dts1 = (dts)get(&queue);
 */
struct Queue *initQueue(struct Queue *queue, int MAXSIZE)
        /*初始化队列*/
{
    queue->maxsize = MAXSIZE;
    queue->size = 0;
    queue->first = NULL;
    queue->last = &(queue->first);
    init_rwlock(&queue->rwlock);
    init_lock(&queue->lock);
    init_pthread_cond(&queue->cont);
    queue->lock_count = 0;
    return queue;
}
/**
 * 向队列中加入任务
 * @param queue
 * @param task
 */
int task_push(struct Queue *queue, void *task)
{
    if(ISNULL(queue)) return thread_err;
    rwlock_wrlock(&queue->rwlock);
    if(queue->maxsize != -1 && queue->maxsize >0 && queue->size > queue->maxsize){
        (void) rwlock_unlock(&queue->rwlock);
        http_write_console(http_stderr, "task queue is full!\n" , 20);
        return thread_err;
    }
    struct queue_task_s *taskt = (struct queue_task_s *)http_calloc(sizeof(struct queue_task_s));
    taskt->task = task;
    taskt->next = NULL;
    if(ISNULL(queue->first))
        queue->first = taskt;
    *(queue->last) = taskt;
    queue->last = &taskt->next;
    atomicIncr(queue->size, 1);
    rwlock_unlock(&queue->rwlock);
    return thread_ok;
}
/***
 * 任务出队
 * @param queue
 * @return
 */
void* task_pop(struct Queue *queue)
{
    void *task = NULL;
    if(ISNULL(queue)) return NULL;
    rwlock_wrlock(&queue->rwlock);
    queue_task_t *taskt = queue->first;
    if(ISNOTNULL(taskt))
    {
        queue->first = taskt->next;
        if (ISNULL(queue->first)) {
            queue->last = &queue->first;
        }
        atomicDecr(queue->size, 1);
        task = taskt->task;
        http_free(taskt);
        rwlock_unlock(&queue->rwlock);
        return task;
    }
    rwlock_unlock(&queue->rwlock);
    return NULL;
}

void push_task_block(struct Queue *queue, void *task) {     // 阻塞方式插入数据
    if(ISNULL(queue)) return ;
    mutex_lock(&queue->lock);
    task_push(queue, task);
    atomicIncr(queue->lock_count, 1);
    pthread_cond_signal(&queue->cont);
    mutex_unlock(&queue->lock);
}
void *pop_task_block(struct Queue *queue) {          // 阻塞方式弹出数据源
    if(ISNULL(queue)) return NULL;
    void* task = NULL;
    mutex_lock(&queue->lock);
    if(queue->lock_count) {
        atomicDecr(queue->lock_count, 1);
    }else{
        pthread_cond_wait(&queue->cont, &queue->lock);
    }
    task = task_pop(queue);
    mutex_unlock(&queue->lock);
    return task;
}
// 以流的方式入队
void stream_push_queue(struct Queue *queue, dts d, int len){
    if(ISNULL(queue)) return ;
    len = len > dtslen(d)? dtslen(d):len;
    dtsrange(d, 0, len);
    task_push(queue, dtsnew(d));
}
// 以流的方式读取数据
char* stream_pop_queue(struct Queue *queue, char *desc, int size){
    if(ISNULL(queue)) return NULL;
//    TODO
    return desc;
}
// 获取队列中数据量
int get_queue_size(struct Queue *queue) {
    if(ISNULL(queue)) return thread_err;
    int size = 0;
    if(ISNULL(queue)) return size;
    mutex_lock(&queue->lock);
    size = queue->size;
    mutex_unlock(&queue->lock);
    return size;
}
// 队列中是否还有数据
int has_queue_next(struct Queue *queue) {
    if(ISNULL(queue)) return thread_err;
    mutex_lock(&queue->lock);
    if(ISNOTNULL(queue->first))
    {
        mutex_unlock(&queue->lock);
        return thread_ok;
    }
    mutex_unlock(&queue->lock);
    return thread_err;
}


/* ================ end of Queue.c ================ */


/* ================ end of Lists.c ================ */
linklist_t* initLinkList(linklist_t *list)                 // 初始化链表
{
    list->size = 0;
    list->head = NULL;
    list->tail = NULL;
    init_rwlock(&list->rwlock);
    init_lock(&list->lock);
    init_pthread_cond(&list->cont);
    return list;
}
static inline void insertnode(linklist_t *list, table_t *tb, table_t *itb, enum InsertType type)  // 插入元素
{
    if(ISNULL(list)) return;
    rwlock_wrlock(&list->rwlock);
    if(ISNULL(list->head) && ISNULL(list->tail) && ISNULL(itb)) // 首次插入
    {
        list->head = list->tail = tb;
        atomicIncr(list->size, 1);
        (void) rwlock_unlock(&list->rwlock);
        return;
    }
    switch (type) {
        case BEFORE:
            tb->next = itb;
            tb->prev = itb->prev;
            if(ISNULL(itb->prev))
                list->head = tb;
            itb->prev = tb;
            break;
        case AFTER:
            tb->next = itb->next;
            tb->prev = itb;
            if(ISNULL(itb->next))
                list->tail = tb;
            itb->next = tb;
            break;
    }
    atomicIncr(list->size, 1);
    (void) rwlock_unlock(&list->rwlock);
}
void inserttable(linklist_t *list, void *val, table_t *itb, enum InsertType type)
{
    if(ISNULL(list)) return;
    struct Table *tb = (struct Table *) http_malloc(sizeof(struct Table));
    tb->value = val;
    tb->next = NULL;
    tb->prev = NULL;
    if(ISNOTNULL(tb))
        insertnode(list, tb, itb, type);
}
void add_linklist_before(linklist_t *list, void *val)          // 追加数据 前面插入
{
    if(ISNULL(list)) return;
    inserttable(list, val, list->head, BEFORE);
}
void add_linklist_after(linklist_t *list, void *val)          // 追加数据 后面插入
{
    if(ISNULL(list)) return;
    inserttable(list, val, list->tail, AFTER);
}
void ready_linklist_data(linklist_t *list)// 元素遍历 游标复位
{
    if(ISNULL(list)) return ;
    rwlock_wrlock(&list->rwlock);
    list->cursor = list->head;
    (void) rwlock_unlock(&list->rwlock);
}
int has_linklist_next(linklist_t *list){
    if(ISNULL(list->cursor))
        return thread_err;
    return thread_ok;
}
table_t *get_linklist(linklist_t *list)
{
    if(ISNULL(list)) return NULL;
    rwlock_wrlock(&list->rwlock);
    table_t * t = list->cursor;
    if(ISNOTNULL(t))
        list->cursor = list->cursor->next;
    (void) rwlock_unlock(&list->rwlock);
    return t;
}
int destry_linklist(linklist_t *list, table_t *tb)                    // 销毁元素
{
    if(ISNULL(list)) return thread_err;
    rwlock_wrlock(&list->rwlock);
    if(ISNOTNULL(tb->prev) && ISNOTNULL(tb->next))
    {
        tb->prev->next = tb->next;
        tb->next->prev = tb->prev;
    }
    if(ISNULL(tb->prev))
    {
        list->head = tb->next;
        if(ISNOTNULL(list->head))
            list->head->prev = NULL;
    }
    if(ISNULL(tb->next))
    {
        list->tail = tb->prev;
        if(ISNOTNULL(list->tail))
            list->tail->next = NULL;
    }
    http_free(tb);
    atomicDecr(list->size, 1);
    (void) rwlock_unlock(&list->rwlock);
    return thread_ok;
}
/* ================ start of Lists.c ================ */
